home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1995 November
/
EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso
/
earcd
/
unix
/
mp14tar.z
/
mp14tar
/
mpack
/
macnapp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-06-01
|
39KB
|
1,485 lines
/* macnapp.c -- macintosh nifty application library
*
* (C) Copyright 1990-1993 by Christopher J. Newman
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Christopher J. Newman not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Christopher J. Newman makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* CHRISTOPHER J. NEWMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
* SHALL CHRISTOPHER J. NEWMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*
* Author: Christopher J. Newman
* Message: This is a nifty program.
*
* BUGS:
* - should check 32bit mode works.
*/
#ifndef THINK_C
#include <Resources.h>
#include <Dialogs.h>
#include <Desk.h>
#include <SegLoad.h>
#include <OSEvents.h>
#include <DiskInit.h>
#include <Traps.h>
#include <ToolUtils.h>
#endif
#include <AppleEvents.h>
#include "macnapp.h"
/* export globals */
na_win **NAhead = (na_win**) NULL; /* head of the window tree */
na_win **NAtask = (na_win**) NULL; /* head of the task list */
na_win **NActask = (na_win**) NULL; /* next task to be called */
na_win *NAwin = (na_win*) NULL; /* the current window */
na_menup NAmenup = (na_menup) NULL; /* application menu procedure */
short NAnewitem = 0; /* the new item number */
short NAcloseitem = 0; /* the close item number */
short NAappleitems = 0; /* number of apple menu items */
Boolean NAhasedit = false; /* true if application supports edit menu */
long NAdelay = 30; /* delay (1/60th of a second) between null events */
SysEnvRec NAsysenv; /* set up by Initialize */
Boolean NAinBack = false; /* true when app is in the background */
short NAlastmouse = NA_RELEASE; /* the last mouse event type */
long NAmousetime = 0; /* the time of the last mouse up */
Point NAmousept; /* the point (local) of last mouse down */
THz NAappzone; /* the application heap zone */
RgnHandle NAfullRgn; /* a region containing everything */
RgnHandle NAnullRgn; /* a region containing nothing */
Cursor NAibeam; /* the Ibeam cursor */
long NAgestaltBits; /* flags for gestalt options */
/* private globals */
static Point mselpoint; /* the menu selection point */
static short aestatus; /* if set, close everything */
/* constants for DoDraw procedure */
#define DO_UPDATE 0x0
#define DO_RESIZE 0x1
#define DO_ACTIVATE 0x2
#define DO_DEACTIVATE 0x4
/* private routines */
static na_win **GetWinH(WindowPtr);
static void DoDraw(na_win*, short);
static short DoActivate(WindowPtr, na_win*, Boolean, Point p);
static short DoMenu(na_win*, BYTE);
static void AdjustCursor(na_win*, Point, Boolean);
static short aboutmouse(na_win*, Point, short, short);
/* get the handle to a window
*/
static na_win **GetWinH(window)
WindowPtr window;
{
na_win **winh;
/* make positively sure that we have a valid handle */
if (window != (WindowPtr) NULL && !NAisDAWindow(window)) {
#ifdef DEBUG
if (PtrZone((Ptr) window) == NAappzone && MemError() == noErr) {
#endif
if ((winh = (na_win **) GetWRefCon(window)) != (na_win**) NULL) {
#ifdef DEBUG
if (HandleZone((Handle) winh) == NAappzone && MemError() == noErr) {
if ((*winh)->pwin == window) {
#endif
return (winh);
#ifdef DEBUG
} else {
NAdebug("Corrupted window structure found.\015");
NAdebug("handle: %lx, pwin: %lx, window: %lx\015",
(long) winh, (long) (*winh)->pwin, (long) window);
Debugger();
}
} else {
NAdebug("Corrupted Handle Zone Found.\015");
NAdebug("handle: %lx, error: %ld\015", (long) winh,
(long) MemError());
Debugger();
}
#endif
}
#ifdef DEBUG
} else {
NAdebug("Corrupted Window Pointer Found.\n");
NAdebug("Pointer: %lx, error: %ld\n", (long) window, (long) MemError());
Debugger();
}
#endif
}
return ((na_win**) NULL);
}
/* handle drawing controls & growbox for update/activate events
*/
#ifdef __STDC__
static void DoDraw(na_win *winp, short how)
#else
static void DoDraw(winp, how)
na_win *winp;
short how;
#endif
{
WindowPtr window = winp->pwin;
long flags = winp->flags;
/* hilite or draw controls as appropriate */
if (flags & NA_HASCONTROLS) {
if (how & (DO_ACTIVATE | DO_DEACTIVATE)) {
if (flags & NA_HILITECTRLS) {
ControlHandle ctrl;
for (ctrl = ((WindowPeek) window)->controlList; ctrl;
ctrl = (*ctrl)->nextControl) {
HiliteControl(ctrl, (how & DO_ACTIVATE) ? 0 : 255);
}
}
} else {
DrawControls(window);
}
}
/* draw the grow box properly -- mask out scroll bar outlines */
if (flags & NA_GROWBOX) {
Rect tmpRect;
RgnHandle tmpRgn = window->clipRgn;
tmpRect.left = (tmpRect.right = window->portRect.right) - 15;
tmpRect.top = (tmpRect.bottom = window->portRect.bottom) - 15;
RectRgn(window->clipRgn = NewRgn(), &tmpRect);
DrawGrowIcon(window);
DisposeRgn(window->clipRgn);
window->clipRgn = tmpRgn;
}
/* draw the default button on a dialog */
if (flags & NA_DEFBUTTON) NAdefaultButton(window);
/* calculate the un-cursor region if the window size changed */
if (how & DO_RESIZE) NAcalcCursor(winp);
}
/* handle activate event (either activate or MultiFinder suspend/resume)
*/
#ifdef __STDC__
static short DoActivate(WindowPtr window, na_win *winp, Boolean activate, Point p)
#else
static short DoActivate(window, winp, activate, p)
WindowPtr window;
na_win *winp;
Boolean activate;
Point p;
#endif
{
na_win **winh;
short status = NA_NOTPROCESSED;
/* unlock current front window */
if (winp != (na_win*) NULL) {
NAunlockWindow(winp);
NAwin = (na_win*) NULL;
}
/* check if there is a new window, and lock it */
if (window == (WindowPtr) NULL) return (NA_PROCESSED);
/* for app windows, update the cursor, call the activate proc, and DoDraw */
if ((NAwin = winp = NAlockWindow(winh = GetWinH(window))) != (na_win*) NULL) {
GrafPtr tmpPort;
GetPort(&tmpPort);
SetPort(window);
if (winp->cursorRgn != (RgnHandle) NULL && ((activate && !NAinBack)
|| winp->flags & NA_CURSORON)) {
LocalToGlobal(&p);
AdjustCursor(winp, p, activate);
}
if (winp->activep == (na_activep) NULL
|| (status = (*winp->activep)(winp, activate)) == NA_NOTPROCESSED) {
DoDraw(winp, activate ? DO_ACTIVATE : DO_DEACTIVATE);
}
if (!activate || winp->pwin != FrontWindow()) {
SetPort(tmpPort);
NAunlockWindowh(winh, winp);
NAwin = (na_win*) NULL;
}
}
return (status);
}
/* handle menu selection -- either menu click or menu shortcut
*/
#ifdef __STDC__
static short DoMenu(na_win *winp, BYTE key)
#else
static short DoMenu(winp, key)
na_win *winp;
BYTE key;
#endif
{
WindowPtr window = FrontWindow();
short status = NA_NOTPROCESSED;
WORD menuid, itemno;
/* enable/disable edit menu as appropriate */
if (NAhasedit) {
MenuHandle mnu = GetMHandle(mEdit);
if (NAisDAWindow(window)) {
EnableItem(mnu, iUndo);
for (itemno = iCut; itemno <= iClear; itemno++) {
EnableItem(mnu, itemno);
}
} else {
DisableItem(mnu, iUndo);
for (itemno = iCut; itemno <= iClear; itemno++) {
DisableItem(mnu, itemno);
}
}
}
/* enable/disable the close menu as appropriate */
if (NAcloseitem) {
MenuHandle mnu = GetMHandle(mFile);
if (window != (WindowPtr) NULL && (winp == (na_win*) NULL
|| winp->pwin != window || winp->flags & NA_CLOSEBOX)) {
EnableItem(mnu, NAcloseitem);
} else {
DisableItem(mnu, NAcloseitem);
}
}
/* call menu proc to enable/disable items as appropriate */
if (winp != (na_win*) NULL && winp->menup != (na_menup) NULL) {
status = (*winp->menup)(winp, (WORD) 0, (WORD) key);
}
if (status == NA_NOTPROCESSED && NAmenup != (na_menup) NULL) {
status = (*NAmenup)(winp, (WORD) 0, (WORD) key);
}
if (status != NA_NOTPROCESSED) return (status);
/* get menu selection */
{
long menusel = (key == 0) ? MenuSelect(mselpoint) : MenuKey(key);
itemno = LOWORD(menusel);
if ((menuid = HIWORD(menusel)) == 0) menuid = 1;
}
/* check for DA menu items */
switch (menuid) {
case mApple: /* check for a desk accessary selection */
if (itemno > NAappleitems) {
PCstr mItem[256];
GetItem(GetMHandle(menuid), itemno, mItem);
OpenDeskAcc(mItem);
menuid = 1;
}
break;
case mFile: /* check for the close menu item for DAs */
if (itemno == NAcloseitem && NAisDAWindow(window)) {
CloseDeskAcc(((WindowPeek) window)->windowKind);
menuid = 1;
}
break;
case mEdit: /* check for the edit menu for DAs */
if (NAhasedit && itemno <= iClear && SystemEdit(itemno - iUndo)) {
menuid = 1;
}
break;
}
/* call menu proc to handle/disable items */
if (winp != (na_win*) NULL && winp->menup != (na_menup) NULL) {
status = (*winp->menup)(winp, menuid, itemno);
}
if (status != NA_PROCESSED && NAmenup != (na_menup) NULL) {
status = (*NAmenup)(winp, menuid, itemno);
}
/* if close item wasn't processed, process it */
if (status == NA_NOTPROCESSED && menuid == mFile && itemno == NAcloseitem) {
status = NA_REQCLOSE;
}
/* turn off the menu */
HiliteMenu(0);
return (status);
}
/* set the cursor icon appropriately
*/
#ifdef __STDC__
static void AdjustCursor(na_win *winp, Point gmouse, Boolean active)
#else
static void AdjustCursor(winp, gmouse, active)
na_win *winp;
Point gmouse;
Boolean active;
#endif
{
short status = NA_NOTPROCESSED;
/* don't change the cursor when in wrong window */
if (active && FrontWindow() != winp->pwin) return;
/* if the cursor is on */
if (winp->flags & NA_CURSORON) {
/* and the point moves outside the cursor region or window is deactivated
* turn cursor off */
if (!active || PtInRgn(gmouse, winp->uncrsrRgn)) {
winp->flags &= ~NA_CURSORON;
if (winp->cursorp == (na_cursorp*) NULL) {
SetCursor(&QD(arrow));
} else {
goto DOCURSORP;
}
}
/* if the cursor is off and the point moves into the window, turn cursor on */
} else if (PtInRgn(gmouse, winp->cursorRgn)) {
winp->flags |= NA_CURSORON;
if (winp->cursorp == (na_cursorp) NULL) {
SetCursor(&NAibeam);
} else {
DOCURSORP:
GlobalToLocal(&gmouse);
status = (*winp->cursorp)(winp, gmouse);
}
}
/* if cursor event was processed, reset the un-cursor region */
if (status == NA_PROCESSED) NAcalcCursor(winp);
}
/* export routines */
/* save the current window position in a resource file
*/
void NAsaveWin(winp)
na_win *winp;
{
Rect *rptr;
WindowPtr window = winp->pwin;
Handle wind = GetResource('WIND', winp->resid);
HLock(wind);
rptr = (Rect *) *wind;
rptr->right = (rptr->left = -window->portBits.bounds.left)
+ window->portRect.right;
rptr->bottom = (rptr->top = -window->portBits.bounds.top)
+ window->portRect.bottom;
ChangedResource(wind);
HUnlock(wind);
}
/* calculate the cursor regions for Multi-Finder
*/
void NAcalcCursor(winp)
na_win *winp;
{
if (winp->cursorRgn != (RgnHandle) NULL) {
if (winp->uncrsrRgn == (RgnHandle) NULL) winp->uncrsrRgn = NewRgn();
DiffRgn(NAfullRgn, winp->cursorRgn, winp->uncrsrRgn);
}
}
/* lock a window context
*/
na_win *NAlockWindow(winh)
na_win **winh;
{
if (winh == (na_win**) NULL) return ((na_win*) NULL);
if (!(*winh)->locks++) {
MoveHHi((Handle) winh);
HLock((Handle) winh);
}
return (*winh);
}
/* request or force a window to close
*/
#ifdef __STDC__
short NAcloseWindow(na_win *winp, short status)
#else
short NAcloseWindow(winp, status)
na_win *winp;
short status;
#endif
{
na_win **winh, ***whp;
short childstatus;
na_closep closeproc = (na_closep) NULL;
if (winp == (na_win*) NULL) return (NA_NOTPROCESSED);
switch (status) {
case NA_REQCLOSE:
/* check if window ready to close */
status = NA_CLOSED;
if ((closeproc = winp->closep) != (na_closep) NULL) {
status = (*closeproc)(winp);
closeproc = winp->closep == closeproc ? (na_closep) NULL : closeproc;
}
if (status > NA_CLOSED) break;
case NA_CLOSED:
/* close children */
childstatus = NAcloseWindows(winp->child, NA_REQCLOSEALL);
/* clear current window */
if (winp == NAwin) NAwin = (na_win*) NULL;
/* reset the cursor */
if (winp->flags & NA_CURSORON) SetCursor(&QD(arrow));
/* dispose of any cursor regions */
if (winp->cursorRgn != (RgnHandle) NULL) DisposeRgn(winp->cursorRgn);
if (winp->uncrsrRgn != (RgnHandle) NULL) DisposeRgn(winp->uncrsrRgn);
/* close the window */
if (winp->pwin != (WindowPtr) NULL) {
if (winp->flags & NA_DIALOGWINDOW) {
DisposDialog((DialogPtr) winp->pwin);
} else {
DisposeWindow(winp->pwin);
}
}
/* remove from window list */
winh = (na_win**) RecoverHandle((Ptr) winp);
#ifdef DEBUG
if (MemError() != noErr || *winh != winp) {
NAdebug("Handle error: pointer: %x, handle: %x, error: %d, zone: %x\015",
(long) winp, (long) winh, (long) MemError(),
(long) GetZone());
Debugger();
}
#endif /* DEBUG */
whp = &NAhead;
if (winp->parent != (na_win**) NULL) whp = &(*winp->parent)->child;
while (*whp != (na_win**) NULL) {
if (*whp == winh) {
*whp = winp->next;
} else {
whp = &(**whp)->next;
}
}
/* relink children in list */
if (childstatus > NA_ALLCLOSED) {
*whp = winp->child;
do {
(**whp)->parent = winp->parent;
whp = &(**whp)->next;
} while (*whp != (na_win**) NULL);
*whp = winp->next;
}
/* remove from task list */
whp = &NAtask;
while (*whp != (na_win**) NULL && *whp != winh) {
whp = &(**whp)->task;
}
*whp = winp->task;
NActask = (na_win**) NULL;
/* after-close function */
if (closeproc != (na_closep) NULL) (*closeproc)(winp);
/* destroy window structure */
DisposHandle((Handle) winh);
if (status < NA_CLOSED) {
if ((status = NAcloseWindows(NAhead, status)) > NA_CLOSED) {
status = NA_CLOSED;
}
}
break;
}
return (status);
}
#ifdef __STDC__
short NAcloseWindows(na_win **winh, short status)
#else
short NAcloseWindows(winh, status)
na_win **winh;
short status;
#endif
{
na_win *winp, **lasth;
short substatus;
while ((winp = NAlockWindow(winh)) != (na_win*) NULL) {
lasth = winh;
winh = winp->next;
substatus = NAcloseWindow(winp, status + 2);
if (substatus > NA_CLOSED) {
NAunlockWindowh(lasth, winp);
return (NA_NOTPROCESSED);
}
if (substatus < NA_CLOSED) return (substatus);
}
return (NA_ALLCLOSED);
}
/* remove the window on a mouse-up event
*/
#ifdef __STDC__
static short aboutmouse(na_win *winp, Point mousep, short type, short mods)
#else
static short aboutmouse(winp, mousep, type, mods)
na_win *winp;
Point mousep;
short type, mods;
#endif
#ifdef applec
#pragma unused (winp, mousep, mods)
#endif
{
return (type & 1 ? NA_REQCLOSE : NA_PROCESSED);
}
/* a standard about box init procedure
*/
short NAabout(winp, dptr)
na_win *winp;
long *dptr;
#ifdef applec
#pragma unused (dptr)
#endif
{
short item;
ShowWindow(winp->pwin);
winp->mousep = aboutmouse;
return (NA_PROCESSED);
}
/* flash a button in a dialog box for equivalent keypresses
*/
#ifdef __STDC__
void NAflashButton(DialogPtr dialog, short item)
#else
void NAflashButton(dialog, item)
DialogPtr dialog;
short item;
#endif
{
long scratch;
short type;
Handle ctrl;
Rect box;
GetDItem(dialog, item, &type, &ctrl, &box);
if (type == ctrlItem + btnCtrl) {
HiliteControl((ControlHandle) ctrl, 1);
Delay(5, &scratch);
HiliteControl((ControlHandle) ctrl, 0);
}
}
/* draw the default button
*/
void NAdefaultButton(dialog)
DialogPtr dialog;
{
Rect tmpRect;
NAgetDRect(dialog, iOk, &tmpRect);
{
PenState pnState;
GetPenState(&pnState);
PenNormal();
PenSize(3, 3);
InsetRect(&tmpRect, -4, -4);
FrameRoundRect(&tmpRect, 16, 16);
SetPenState(&pnState);
}
}
/* send an event message to all windows
*/
short NAallWindows(winh, pevent)
na_win **winh;
EventRecord *pevent;
{
na_win *winp, **oldwinh;
short status = NA_NOTPROCESSED;
while ((winp = NAlockWindow(winh)) != (na_win*) NULL) {
oldwinh = winh;
winh = winp->next;
if (winp->miscp != (na_miscp) NULL) {
GrafPtr tempPort;
GetPort(&tempPort);
SetPort(winp->pwin);
status = (*winp->miscp)(winp, pevent);
SetPort(tempPort);
}
if ((status == NA_CLOSED || status == NA_REQCLOSE)
&& NAcloseWindow(winp, status) == NA_CLOSED) {
continue;
}
NAunlockWindowh(oldwinh, winp);
if (status == NA_ALLCLOSED || status == NA_REQCLOSEALL) {
if (NAcloseWindows(NAhead, status) == NA_ALLCLOSED) {
return (NA_ALLCLOSED);
}
/* make sure our handle is still valid */
if (GetHandleSize((Handle) oldwinh) == 0) continue;
}
if ((*oldwinh)->child != (na_win**) NULL &&
NAallWindows((*oldwinh)->child, pevent) == NA_ALLCLOSED) {
return (NA_ALLCLOSED);
}
}
return (NA_PROCESSED);
}
/* apple event handler
*/
pascal OSErr NArequiredAE(AppleEvent *, AppleEvent *, long);
pascal OSErr NArequiredAE(event, reply, ref)
AppleEvent *event, *reply;
long ref;
{
na_openp openp = (na_openp) ref;
OSErr err;
DescType actualType, eventID;
Size actualSize;
AEDescList doclist;
long count, i;
short gotdoc;
FSSpec fspec;
AEKeyword keywd;
err = AEGetAttributePtr(event, keyEventIDAttr, typeType, &actualType,
(Ptr) &eventID, sizeof (eventID), &actualSize);
if (err == noErr) {
gotdoc = 0;
if (eventID == kAEOpenDocuments || eventID == kAEPrintDocuments) {
err = AEGetParamDesc(event, keyDirectObject, typeAEList, &doclist);
if (err == noErr) gotdoc = 1;
}
if (err == noErr) {
err = AEGetAttributePtr(event, keyMissedKeywordAttr, typeWildCard,
&actualType, NULL, 0, &actualSize);
if (err == errAEDescNotFound) {
err = noErr;
} else if (err == noErr) {
err = errAEEventNotHandled;
}
}
if (err == noErr) switch (eventID) {
case kAEOpenApplication:
if (NAmenup && NAnewitem) {
aestatus = (*NAmenup)(NULL, mFile, NAnewitem);
}
break;
case kAEOpenDocuments:
case kAEPrintDocuments:
err = AECountItems(&doclist, &count);
if (err != noErr) break;
for (i = 1; i <= count; ++i) {
err = AEGetNthPtr(&doclist, i, typeFSS, &keywd, &actualType,
(Ptr) &fspec, sizeof (fspec), &actualSize);
if (err != noErr) break;
if (!openp || (*openp)(eventID == kAEOpenDocuments
? appOpen : appPrint, 0, &fspec) < 0) {
err = errAEEventNotHandled;
break;
}
}
break;
case kAEQuitApplication:
aestatus = NA_ALLCLOSED;
if (NAhead != NULL) {
aestatus = NAcloseWindows(NAhead, NA_REQCLOSEALL);
if (aestatus != NA_ALLCLOSED) err = userCanceledErr;
}
break;
}
if (gotdoc) {
AEDisposeDesc(&doclist);
}
}
return (err);
}
/* call the main loop procedure
*/
void NAmainloop()
{
na_win *winp;
Boolean gotEvent;
Boolean dialogAction;
EventRecord event;
Point mouse;
short status;
short itemHit;
DialogPtr dialog;
UnloadSeg((Ptr) NAinit); /* unload the initialize routine */
MAINLOOP:
/* check for a window in front */
{
WindowPtr window;
if ((winp = NAwin) == (na_win*) NULL
&& (window = FrontWindow()) != (WindowPtr) NULL
&& (NAwin = winp = NAlockWindow(GetWinH(window))) != (na_win *) NULL) {
SetPort(window);
}
}
/* get an event */
{
RgnHandle rgn = NAfullRgn;
short delay = NAdelay;
/* if there is an app window in front, use app delay & cursor region */
if (winp != (na_win*) NULL) {
delay = winp->delay;
if (winp->cursorRgn != (RgnHandle) NULL && !NAinBack) {
rgn = winp->cursorRgn;
if (!(winp->flags & NA_CURSORON)) rgn = winp->uncrsrRgn;
}
if (winp->mousepix && !(NAlastmouse & 1)) {
rgn = NAnullRgn;
delay = 0;
}
}
gotEvent = WaitNextEvent(everyEvent, &event, delay, rgn);
}
status = NA_NOTPROCESSED;
/* get mouse position */
mouse = event.where;
GlobalToLocal(&mouse);
/* check for dialog events */
dialogAction = FrontWindow() != (WindowPtr) NULL ? IsDialogEvent(&event) : false;
if (dialogAction && event.what != keyDown && event.what != autoKey
&& event.what != updateEvt) {
ControlHandle ctrl;
if (DialogSelect(&event, &dialog, &itemHit) && winp != (na_win*) NULL) {
DOCONTROLP:
if (winp->ctrlp != (na_ctrlp) NULL) {
NAgetDHandle(dialog, itemHit, &ctrl);
status = (*winp->ctrlp)(winp, mouse, itemHit, event.modifiers, ctrl);
gotEvent = false;
}
}
}
/* handle the event */
if (gotEvent) switch (event.what) {
case mouseUp:
/* deal with mouse up events to keep track of double/triple clicks */
if (NAlastmouse & 1) break;
++NAlastmouse;
NAmousetime = TickCount();
if (winp == (na_win*) NULL) break;
DOMOUSEP:
if (winp->mousep != (na_mousep) NULL) {
status = (*winp->mousep)(winp, mouse, NAlastmouse, event.modifiers);
}
break;
case mouseDown:
if (winp != (na_win*) NULL && winp->flags & NA_MODAL
&& !PtInRect(mouse, &winp->pwin->portRect)) {
SysBeep(10);
break;
}
{
short part;
WindowPtr window;
/* deal with mouse down events */
switch (part = FindWindow(event.where, &window)) {
case inMenuBar:
/* call an appropriate menu bar handler */
mselpoint = event.where;
status = DoMenu(winp, 0);
break;
case inSysWindow:
/* System Click in DA */
SystemClick(&event, window);
break;
case inContent:
/* click a window to front if not in front */
if (window != FrontWindow()) {
SelectWindow(window);
if (winp != (na_win*) NULL) NAunlockWindow(winp);
NAwin = (na_win*) NULL;
NAlastmouse = NA_RELEASE;
break;
}
/* don't bother processing further if no mouse proc */
if (winp == (na_win*) NULL) break;
/* check for control events */
if (winp->ctrlp != (na_ctrlp) NULL && winp->flags & NA_HASCONTROLS) {
ControlHandle hctl;
short item;
if ((item = FindControl(mouse, window, &hctl)) != 0
&& (status = (*winp->ctrlp)(winp, mouse, item,
event.modifiers, hctl)) != NA_NOTPROCESSED) {
break;
}
}
/* deal with double clicks */
if ((NAlastmouse & 1) && NAlastmouse < NA_RELEASE
&& event.when - NAmousetime <= GetDblTime()) {
if (++NAlastmouse > NA_DOWNN) NAlastmouse = NA_DOWNN;
} else {
NAlastmouse = NA_DOWN1;
}
NAmousept = mouse;
/* call the mouse handler */
goto DOMOUSEP;
case inDrag:
/* drag the window */
{
Rect tmpRect, bRect;
na_win **wh, *wp;
{
int four = 4;
tmpRect = QD(screenBits.bounds);
InsetRect(&tmpRect, four, four);
}
bRect = window->portBits.bounds;
DragWindow(window, event.where, &tmpRect);
if ((bRect.left != window->portBits.bounds.left
|| bRect.top != window->portBits.bounds.top) &&
(wp = NAlockWindow(wh = GetWinH(window))) != NULL) {
if (wp->flags & NA_SMARTSIZE) NAsaveWin(wp);
if (wp->cursorRgn != (RgnHandle) NULL) {
OffsetRgn(wp->cursorRgn,
bRect.left - window->portBits.bounds.left,
bRect.top - window->portBits.bounds.top);
NAcalcCursor(wp);
}
NAunlockWindowh(wh, wp);
}
}
break;
case inGoAway:
/* deal with the close window box */
if (TrackGoAway(window, event.where)) status = NA_REQCLOSE;
break;
case inGrow:
/* grow the window */
{
Rect tmpRect;
long growInfo;
/* assume there is a valid app window in front */
/* calculate min & max grow dimensions */
tmpRect = QD(screenBits.bounds);
tmpRect.bottom -= tmpRect.top;
tmpRect.right -= tmpRect.left;
tmpRect.top = winp->minh;
tmpRect.left = winp->minw;
if (winp->maxh) tmpRect.bottom = winp->maxh;
if (winp->maxw) tmpRect.right = winp->maxw;
/* check for resize proc */
if (winp->resizep != (na_resizep) NULL) {
status = (*winp->resizep)(winp, event.where, &tmpRect);
if (status == NA_PROCESSED) break;
goto RESIZEWINDOW;
}
/* grow, resize, and update the window */
if ((growInfo = GrowWindow(window, event.where, &tmpRect))) {
SizeWindow(window, LOWORD(growInfo), HIWORD(growInfo),
false);
goto RESIZEWINDOW;
}
}
break;
case inZoomIn:
case inZoomOut:
/* assume there is a valid app window in front */
/* track, zoom, and update the window */
if (TrackBox(window, event.where, part)) {
SetPort(window);
EraseRect(&window->portRect);
ZoomWindow(window, part, true);
RESIZEWINDOW:
if (winp != (na_win*) NULL) {
if (winp->flags & NA_SMARTSIZE) NAsaveWin(winp);
if (winp->updatep == (na_updatep) NULL ||
(status = (*winp->updatep)(winp, (Boolean) true))
== NA_NOTPROCESSED) {
DoDraw(winp, DO_RESIZE);
}
}
ValidRect(&window->portRect);
}
break;
}
}
break;
case keyDown:
case autoKey:
/* deal with keyboard events */
{
long key = event.message & charCodeMask;
/* translate command-foo to an appropriate menu operation */
if (!(winp->flags & NA_MODAL)) {
if ((event.modifiers & cmdKey) && event.what == keyDown &&
(status = DoMenu(winp, key)) != NA_NOTPROCESSED) {
break;
}
}
/* require an app window for further processing */
if (winp == (na_win*) NULL) break;
/* call the window's key handling procedure */
if (winp->keyp != (na_keyp) NULL) {
status = (*winp->keyp)(winp, winp->flags & NA_RAWKEY ? event.message : key,
event.modifiers);
}
/* if it's an unprocessed event in a dialog window */
if ((status == NA_NOTPROCESSED || status == NA_DPROCESSED)
&& (winp->flags & NA_DIALOGWINDOW)) {
ControlHandle ctrl;
/* check for return/ESC/command-. */
itemHit = 0;
if (status == NA_NOTPROCESSED) switch (key) {
case '\r':
case '\n':
NAgetDHandle((DialogPtr)winp->pwin, iOk, &ctrl);
if (ctrl && !(*ctrl)->contrlHilite) {
itemHit = iOk;
}
break;
case '.':
if (!(event.modifiers & cmdKey)) break;
case '\033':
itemHit = iCancel;
break;
}
/* if it's a special key, flash it's item */
dialog = winp->pwin;
if (itemHit) {
NAflashButton(dialog, itemHit);
} else if ((event.modifiers & cmdKey)
|| !DialogSelect(&event, &dialog, &itemHit)) {
break;
}
/* if there's a control procedure, call it, otherwise ignore */
if (winp->ctrlp != (na_ctrlp) NULL) goto DOCONTROLP;
}
}
break;
case activateEvt:
/* deal with activate windows based on activeFlag */
status = DoActivate((WindowPtr) event.message, winp,
event.modifiers & activeFlag, mouse);
break;
case updateEvt:
/* deal with update events with proper port setting, etc. */
{
na_win *wp;
WindowPtr window;
na_win **winh;
GrafPtr tempPort;
window = (WindowPtr) event.message;
BeginUpdate(window);
if ((wp = NAlockWindow(winh = GetWinH(window))) != (na_win*) NULL) {
GetPort(&tempPort);
SetPort(window);
if (wp->flags & NA_DIALOGUPDATE) {
UpdtDialog(window, window->visRgn);
status = NA_PROCESSED;
}
if (wp->updatep == (na_updatep) NULL
|| (status = (*wp->updatep)(wp, (Boolean) false))
== NA_NOTPROCESSED) {
DoDraw(wp, DO_UPDATE);
}
if (status == NA_NOTPROCESSED && dialogAction) {
(void) DialogSelect(&event, &dialog, &itemHit);
}
SetPort(tempPort);
NAunlockWindowh(winh, wp);
}
EndUpdate(window);
}
break;
case diskEvt:
/* let the user format bad disks */
if (HIWORD(event.message) != noErr) {
Point ptemp;
SetPt(&ptemp, 0x0070, 0x0050);
(void) DIBadMount(ptemp, event.message);
} else {
status = NAallWindows(NAhead, &event);
}
break;
case networkEvt:
case driverEvt:
case app1Evt:
case app2Evt:
case app3Evt:
/* send event to all windows */
status = NAallWindows(NAhead, &event);
break;
case osEvt:
switch ((event.message >> 24) & 0xff) {
case suspendResumeMessage:
status = DoActivate(FrontWindow(), winp,
!(NAinBack = !(event.message & resumeFlag)), mouse);
break;
case mouseMovedMessage:
/* only interesting if a window is in front */
if (NAinBack || winp == (na_win*) NULL) break;
{
short mousepix = winp->mousepix;
/* deal with mouse dragging */
if (mousepix && !(NAlastmouse & 1)) {
if (NAlastmouse != NA_DRAG) {
Rect tmpRect;
InsetRect(&tmpRect, -mousepix, -mousepix);
if (PtInRect(mouse, &tmpRect)) break;
NAlastmouse = NA_DRAG;
}
goto DOMOUSEP;
/* deal with cursor moving in/out of window */
} else if (winp->cursorRgn != (RgnHandle) NULL) {
AdjustCursor(winp, event.where, true);
}
}
break;
}
break;
case kHighLevelEvent:
if (NAgestaltBits & NA_HASAEVENTS) {
aestatus = status;
(void) AEProcessAppleEvent(&event);
status = aestatus;
}
break;
}
/* call the idle procedure of the front window */
if ((winp = NAwin) != (na_win*) NULL && !NAinBack
&& status >= NA_NOTPROCESSED && winp->idlep != (na_idlep) NULL) {
status = (*winp->idlep)(winp);
}
/* deal with window/app close requests and events */
switch (status) {
case NA_ALLCLOSED:
case NA_REQCLOSEALL:
status = NAcloseWindows(NAhead, status);
break;
case NA_CLOSED:
case NA_REQCLOSE:
status = NAcloseWindow(winp, status);
break;
default:
/* call the next task procedure */
if (NAtask != (na_win**) NULL) {
static BYTE prioritycnt;
na_win *wp;
GrafPtr tempPort;
if (NActask == (na_win**) NULL) {
NActask = NAtask;
prioritycnt = (*NAtask)->priority;
}
if ((wp = NAlockWindow(NActask)) != (na_win*) NULL
&& wp->taskp != (na_taskp) NULL) {
GetPort(&tempPort);
if (wp->pwin != (WindowPtr) NULL) SetPort(wp->pwin);
switch (status = (*wp->taskp)(wp)) {
case NA_REQCLOSE:
case NA_CLOSED:
NAcloseWindow(wp, status);
break;
}
SetPort(tempPort);
}
if (!prioritycnt-- && (NActask = wp->task) != (na_win**) NULL) {
prioritycnt = (*NActask)->priority;
}
NAunlockWindowh(NActask, wp);
}
break;
}
if (status != NA_ALLCLOSED) goto MAINLOOP;
while (NAtask != NULL) NAcloseWindow(NAlockWindow(NAtask), NA_REQCLOSE);
DisposeRgn(NAfullRgn);
DisposeRgn(NAnullRgn);
}
/* position a rectangle based on screen size
*/
#ifdef __STDC__
Rect *NAscreenrect(short position)
#else
Rect *NAscreenrect(position)
short position;
#endif
{
static short stacktimes = 0;
static Rect sb;
short topoffset, leftoffset;
/* calculate the position to open the window */
{
int four = 4;
sb = QD(screenBits.bounds);
InsetRect(&sb, four, four);
sb.top += MBarHeight;
}
if (position & NA_TITLEOFFSET) {
sb.top += 18;
}
{
short width, height;
width = sb.right - sb.left;
height = sb.bottom - sb.top;
if (position & 0x03) {
width = (width * (position & 0x03)) >> 2;
}
if (position & 0x0c) {
height = (height * ((position & 0x0c) >> 2)) >> 2;
}
if (position & NA_TOPSCN) {
sb.bottom = sb.top + height;
} else if (position & NA_BOTTOMSCN) {
sb.top = sb.bottom - height;
} else {
short bw = (sb.bottom - sb.top - height) >> 1;
sb.top += bw;
sb.bottom -= bw;
}
if (position & NA_LEFTSCN) {
sb.right = sb.left + width;
} else if (position & NA_RIGHTSCN) {
sb.left = sb.right - width;
} else {
short bw = (sb.right - sb.left - width) >> 1;
sb.left += bw;
sb.right -= bw;
}
if (position & NA_STACK) {
if (stacktimes >= 5) {
stacktimes = 0;
}
topoffset = 22 * stacktimes;
leftoffset = (4 - stacktimes) * 4;
if (sb.top + topoffset < sb.bottom) sb.top += topoffset;
if (sb.left + leftoffset < sb.right) sb.left += leftoffset;
++stacktimes;
}
}
return (&sb);
}
/* create a new window/dialog/task structure
*/
#ifdef __STDC__
short NAwindow(Rect *rpos, long flags, char *title, short res, long *initdata,
long datasize, na_initp initp)
#else
short NAwindow(rpos, flags, title, res, initdata, datasize, initp)
Rect *rpos;
long flags;
char *title;
short res;
long *initdata;
long datasize;
na_initp initp;
#endif
{
GrafPtr tmpPort;
short procID;
short status;
Boolean goAwayFlag, visible;
na_win **winh, *winp;
WindowPtr behind, prev;
PCstr wtitle[256];
/* save previous window */
prev = FrontWindow();
/* set up flags for the NewWindow call */
goAwayFlag = (flags & NA_CLOSEBOX);
visible = (flags & NA_NOTVISIBLE) ? false : true;
behind = (flags & NA_BEHIND && NAwin != (na_win*) NULL) ? NAwin->pwin : (WindowPtr) -1;
/* decide on the correct procID */
{
short proc = rDocProc;
if ((flags & NA_ROUNDBORDER) != NA_ROUNDBORDER) {
proc = plainDBox;
if (flags & NA_SHADOWBORDER) proc = altDBoxProc;
if (flags & NA_DOUBLEBORDER) proc = dBoxProc;
if (flags & NA_TITLEBAR) proc = documentProc;
if (!(flags & NA_GROWBOX)
&& proc == documentProc) proc |= noGrowDocProc;
if (flags & NA_ZOOMBOX) proc |= zoomDocProc;
}
procID = proc;
}
/* get the window title to a pacsal string */
if (title) CtoPCstrcpy(wtitle, title);
/* allocate memory and copy the user data */
if (!datasize) datasize = sizeof (na_win);
winh = (na_win**) NewHandleClear((Size) datasize);
if (winh == (na_win**) NULL) return (NA_NOTPROCESSED);
MoveHHi((Handle) winh);
HLock((Handle) winh);
winp = *winh;
if (initdata != NULL && flags & NA_COPYDATA) {
char *newdata;
char *dcopy = (char *) initdata;
datasize -= sizeof (na_win);
for (newdata = (char*) winp + sizeof (na_win); datasize > 0; datasize--) {
*newdata = *dcopy++;
newdata++;
}
}
/* initialize winp parameters */
winp->locks = 1;
winp->delay = NAdelay;
winp->flags = flags;
winp->minw = 128;
winp->minh = 64;
winp->resid = res;
/* install in window tree */
if (flags & NA_CHILDWINDOW && NAwin != (na_win*) NULL) {
winp->parent = (na_win**) RecoverHandle((Ptr)NAwin);
winp->next = NAwin->child;
NAwin->child = winh;
} else {
winp->next = NAhead;
NAhead = winh;
}
/* install in task list */
if (flags & NA_HASTASK) {
winp->task = NAtask;
NAtask = winh;
}
{
WindowPtr window;
/* open the window appropriately */
switch (flags & (NA_COLORWINDOW | NA_DIALOGWINDOW)) {
case NA_DIALOGWINDOW:
case (NA_DIALOGWINDOW | NA_COLORWINDOW):
if (flags & NA_USERESOURCE) {
window = (WindowPtr) GetNewDialog(res, (Ptr) NULL, behind);
} else {
Handle items;
items = GetResource('DITL', res);
DetachResource(items);
if (flags & NA_COLORWINDOW) {
window = (WindowPtr) NewCDialog((Ptr) NULL, rpos, wtitle,
visible, procID, behind, goAwayFlag, (long) winh, items);
} else {
window = (WindowPtr) NewDialog((Ptr) NULL, rpos, wtitle,
visible, procID, behind, goAwayFlag, (long) winh, items);
}
}
break;
case NA_COLORWINDOW:
if (flags & NA_USERESOURCE) {
window = (WindowPtr) GetNewCWindow(res, (Ptr) NULL, behind);
} else {
window = (WindowPtr) NewCWindow((Ptr) NULL, rpos, wtitle,
visible, procID, behind, goAwayFlag, (long) winh);
}
break;
default:
if (flags & NA_USERESOURCE) {
window = GetNewWindow(res, (Ptr) NULL, behind);
} else {
window = NewWindow((Ptr) NULL, rpos, wtitle, visible, procID,
behind, goAwayFlag, (long) winh);
}
break;
}
if (title && (flags & NA_USERESOURCE)) SetWTitle(window, wtitle);
winp->pwin = window;
/* activate the window */
GetPort(&tmpPort);
SetPort(window);
/* additional options for windows from resources */
if (flags & NA_USERESOURCE) {
SetWRefCon(window, (long) winh);
/* force the size */
if (flags & NA_FORCESIZE) {
MoveWindow(window, rpos->left, rpos->top, false);
SizeWindow(window, rpos->right - rpos->left, rpos->bottom - rpos->top, false);
}
}
{
Rect wsize, sb;
/* get the screen bounds */
{
short four = 4;
sb = QD(screenBits.bounds);
InsetRect(&sb, four, four);
}
/* recenter a window -- great for dialog boxes */
wsize = window->portRect;
LocalToGlobal((Point *)&wsize.top);
if (flags & NA_RECENTER) {
LocalToGlobal((Point *)&wsize.bottom);
wsize.top = sb.top + (((sb.bottom - sb.top) - (wsize.bottom - wsize.top)) >> 1);
wsize.left = sb.left + (((sb.right - sb.left) - (wsize.right - wsize.left)) >> 1);
MoveWindow(window, wsize.left, wsize.top, false);
}
/* make sure the window is on the screen */
if (wsize.top > sb.bottom || wsize.left > sb.right) {
short coord = 60;
MoveWindow(window, coord, coord, false);
}
}
/* call the init procedure */
if ((status = (*initp)(winp, initdata)) >= NA_NOTPROCESSED) {
/* draw the window immediately for better look & update has first newsize */
if (winp->updatep == (na_updatep) NULL
|| (status = (*winp->updatep)(winp, (Boolean) true))
== NA_NOTPROCESSED) {
DoDraw(winp, FrontWindow() != window ? DO_RESIZE | DO_DEACTIVATE :
DO_RESIZE);
}
if (flags & NA_DIALOGUPDATE) DrawDialog(window);
ValidRect(&window->portRect);
}
/* deal with close requests/events result codes */
switch (status) {
case NA_ALLCLOSED:
case NA_REQCLOSEALL:
status = NAcloseWindows(NAhead, status);
break;
case NA_CLOSED:
case NA_REQCLOSE:
status = NAcloseWindow(winp, status);
break;
default:
NAunlockWindowh(winh, winp);
break;
}
/* give a nice return value & clean up the port */
if (status == NA_NOTPROCESSED) status = NA_PROCESSED;
if (FrontWindow() != window || status != NA_PROCESSED) SetPort(tmpPort);
}
return (status);
}
/* add a new task to the task list, calling init procedure with data pointer
*/
void NAaddtask(taskp, size)
na_taskp taskp;
long size;
{
na_win **task, *winp;
if (!size) size = sizeof (na_win);
task = (na_win **) NewHandleClear(size);
(*task)->taskp = taskp;
(*task)->task = NAtask;
NAtask = task;
}